package edu.hawaii.duedates;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import edu.hawaii.duedates.libraries.HSLLibrary;
import edu.hawaii.duedates.libraries.UHMLibrary;
import edu.hawaii.duedates.parser.DueDatesParser;
import edu.hawaii.duedates.parser.Option;

/**
 * LibraryManager is responsible for retrieving and processing library related tasks.
 * @author Anthony M. Du
 * 
 */
public class LibraryManager {
  // DueDates parser.
  private final DueDatesParser parser;
  // List of libraries.
  private final List<Library> libraries = new ArrayList<Library>();

  /**
   * LibraryManager constructor which passes a String array through its arguments.
   * @param args  String array of arguments.
   */
  public LibraryManager(String[] args) {
    parser = new DueDatesParser(args);
    handleLibraryOptions();
  }

  /**
   * GetLibraries gets a list of all libraries parsed from arguments.
   * @return libraries Library list.
   */
  public List<Library> getLibraries() {
    if (parser.isSort()) {
      Collections.sort(libraries);
    }
    return libraries;
  }

  /**
   * GetBooks gets a list of all library books.
   * @param lib Library object.
   * @return books from a given library.
   */
  public List<Book> getBooks(Library lib) {
    if (parser.isWithin()) {
      int numDays = parser.withinNum();
      if (numDays <= 0) {
        return lib.getBooks();
      }
      // Current time frame.
      Calendar currentTimeFrame = Calendar.getInstance();
      // List of books within time range.
      List<Book> withinBooks = new ArrayList<Book>();
      // Loop through each library book.
      for (Book b : lib.getBooks()) {
        Date dueDate = b.getDuedate();
        String bookInfo = b.getTitle();
        // Current time range exceeds due date (late book).
        if (currentTimeFrame.after(dueDate)) { 
          withinBooks.add(new Book(bookInfo, dueDate));
        }
        else {
          // 1 day = 86400000 milliseconds.
          long numMilliSeconds = 86400000L * numDays;
          // Time frame range for from due date and within number of days (in milliseconds).
          long dueDateRange = dueDate.getTime() - numMilliSeconds;
          // Current time frame.
          long currentTimeRange = currentTimeFrame.getTime().getTime();
          if (dueDateRange < currentTimeRange) {
            withinBooks.add(new Book(bookInfo, dueDate));
          }
        }
      }
      if (parser.isSort() && parser.sortType().equals("duedate")) {
        Collections.sort(withinBooks);
        return withinBooks;
      }
      return withinBooks;
    }
    else if (parser.isSort() && parser.sortType().equals("duedate")) {
      Collections.sort(lib.getBooks());
      return lib.getBooks();
    }
    return lib.getBooks();
  }

  /**
   * Handles library options given options of either "-uhm" or "-hsl".
   */
  private void handleLibraryOptions() {
    Option console = parser.findOption("-console");
    Option email = parser.findOption("-email");
    
    if (console == null && email == null) {
      System.err.println("Please specifiy at least one of the following options: " +
                          " \"-console\" or \"-email\"");
    }
//    if (console != null) {
//      // handle console option
//    }
//    if (email != null) {
//      // handle email option
//    }
    
    Option uhmOpt = parser.findOption("-uhm");
    Option hslOpt = parser.findOption("-hsl");
    
    if (uhmOpt != null) {
      handleLibraryLoginOf(uhmOpt.getOptName());
    }
    if (hslOpt != null) {
      handleLibraryLoginOf(hslOpt.getOptName());
    }
  }

  /**
   * Handles library login given the options of either "-uhm" or "-hsl".
   * @param libOptName  library option name.
   */
  private void handleLibraryLoginOf(String libOptName) {
    Option libOpt = parser.findOption(libOptName);
    try {
      if (libOpt != null) {
        String login = libOpt.getOptParams().get(0);
        String password = libOpt.getOptParams().get(1);

        if (libOpt.getOptName().equals("-uhm")) {
          Library lib = new UHMLibrary();
          lib.addLibUser(new LibraryUser(login, password));
          libraries.add(lib);  
        } 
        else if (libOpt.getOptName().equals("-hsl")) {
          Library lib = new HSLLibrary();
          lib.addLibUser(new LibraryUser(login, password));
          libraries.add(lib);
        }
      }
    }
    catch (IndexOutOfBoundsException e) {
      System.err.println("Wrong number of arguments for library option: \"" + libOptName + "\"\n" +
          "Example usage: " + libOptName + " [id] [password]");
      if (parser.isVerbose()) {
        e.printStackTrace();
      }
    }
  }
}
